package com.eastmoney.emis.edda.infrastructure.actuate;

import com.eastmoney.emis.context.helper.ThreadPoolHelper;
import com.eastmoney.emis.context.helper.UserActionHelper;
import com.eastmoney.emis.edda.config.KeyHolder;
import com.eastmoney.emis.logger.LoggerFactory;
import com.eastmoney.emis.utils.common.po.UserAction;
import com.eastmoney.emis.utils.common.utils.JSONUtils;
import org.bouncycastle.openpgp.PGPKeyRing;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.pgpainless.PGPainless;
import org.slf4j.Logger;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import sop.exception.SOPGPException;

import java.io.IOException;
import java.time.Duration;
import java.time.Instant;

/**
 * @description: Description
 * @projectName: EDDA-HSBC
 * @package: com.eastmoney.emis.edda.infrastructure
 * @author: 汪程程
 * @date: 2023/7/15 1:31 PM
 * @version: 1.0
 */
public class PGPCertificateHealthIndicator extends AbstractHealthIndicator {

    private static final Logger log = LoggerFactory.getModuleLogger(PGPCertificateHealthIndicator.class, "thirdParty", "user_action");

    private KeyHolder keyHolder;
    private PGPCertificateHealthIndicatorProperties properties;

    private Instant lastCheckTimestamp;

    public PGPCertificateHealthIndicator(KeyHolder keyHolder, PGPCertificateHealthIndicatorProperties properties) {
        this.keyHolder = keyHolder;
        this.properties = properties;
    }

    @Override
    protected void doHealthCheck(Health.Builder builder) {
        if (lastCheckTimestamp != null && lastCheckTimestamp.plus(properties.getWarningPeriod())
                .isAfter(Instant.now())) {
            builder.up();
            return;
        }
        certificateHealthCheck("hsbc.pub", keyHolder.getHsbcPublicKey(), builder);
        certificateHealthCheck("emis_edda.key", keyHolder.getEmisPrivateKey(), builder);
        lastCheckTimestamp = Instant.now();
    }

    private void certificateHealthCheck(String name, String certificate, Health.Builder builder) {
        // 获取证书过期时间
        Instant expiredTime = getExpiredTime(certificate);
        // 获取配置的预警时间间隔
        Duration warningPeriod = properties.getWarningBeforeExpired();
        // 判断是否已进入预警区间
        if (Instant.now().plus(warningPeriod).isAfter(expiredTime)) {
            log(name, expiredTime);
        }
        builder.up();
    }


    private Instant getExpiredTime(String certificate) {
        PGPKeyRing keyRing;
        try {
            keyRing = PGPainless.readKeyRing().keyRing(certificate);
            PGPPublicKey publicKey = keyRing.getPublicKey();
            long validSeconds = publicKey.getValidSeconds();
            return publicKey.getCreationTime().toInstant().plusSeconds(validSeconds);
        } catch (IOException e) {
            throw new SOPGPException.BadData(e);
        }
    }

    private void log(String certificateName, Instant expireDate) {
        UserAction userAction = UserActionHelper.getUserAction(UserActionHelper.Level.INFO, "证书校验");
        userAction.setResult("1");
        userAction.setLogType("WARN");
        userAction.setErrorMsg(certificateName + "即将过期 :" + expireDate.toString());
        ThreadPoolHelper.threadPoolTaskExecutor().submit(() -> log.info(JSONUtils.toJSONString(userAction)));
    }
}
